package com.navinfo.platform.insurance.service;

import com.google.common.collect.Lists;
import com.navinfo.platform.basicdatastatistics.utils.BigDataUtils;
import com.navinfo.platform.common.service.IDataHandleService;
import com.navinfo.platform.insurance.dto.DrivingReport;
import org.apache.spark.api.java.function.MapPartitionsFunction;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Encoders;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;
import scala.collection.mutable.WrappedArray;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

public enum DrivingReportDataHandleService implements IDataHandleService {
    INS;
    @Override
    public void handle(List<Object> obj, Map<String, String> configMap, SparkSession spark) {
        //Broadcast<Long> spanMonthsVar = new JavaSparkContext(spark.sparkContext()).broadcast(Long.valueOf(spanMs));

        Dataset<DrivingReport> drivingReportDS = ((Dataset)obj.get(0)).mapPartitions((MapPartitionsFunction<Row, DrivingReport>) input -> {
            List<DrivingReport>  list = new ArrayList<>();
            while(input.hasNext()){
                Row row = input.next();
                DrivingReport reportDto = new DrivingReport();
                reportDto.setTid(row.getAs("tid"));
                reportDto.setVin(row.getAs("vin"));

                //计算跨度天数
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
                WrappedArray.ofRef<String> start_day = row.getAs("start_day");;
                LocalDate beginDate = null;
                String[] startDayArr = start_day.array();
                for(int i=0; i<startDayArr.length; i++){
                    LocalDate tmpDate = LocalDate.parse(startDayArr[i], df);
                    beginDate = (i==0) ? tmpDate : (beginDate.isAfter(tmpDate) ? tmpDate : beginDate);
                }
                LocalDate endDate = null;
                WrappedArray.ofRef<String> end_day = row.getAs("end_day");;
                String[] endDayArr = end_day.array();
                for(int i=0; i<endDayArr.length; i++){
                    LocalDate tmpDate = LocalDate.parse(endDayArr[i], df);
                    endDate = (i==0) ? tmpDate : (endDate.isBefore(tmpDate) ? tmpDate : endDate);
                }

                //跨度天数
                long spanDays = beginDate.until(endDate, ChronoUnit.DAYS)+1;

                //跨度月数
                long  spanMonths = ((Double)Math.ceil(divide(spanDays, 30L))).longValue();

                //扩展系数
                float coefficient = divide(12, spanMonths);

                long operDays = Optional.ofNullable((Long)row.getAs("operate_days")).orElse(0L);
                //运营天数扩展
                reportDto.setTrip_day_count(multiply(operDays, coefficient).floatValue());
                reportDto.setOperate_activity( divide(operDays, spanDays ));
                reportDto.setOperate_days_monthly( divide(operDays, spanMonths ));

                long weekdayDays = Optional.ofNullable((Long)row.getAs("weekday_days")).orElse(0L);
                //工作日天数扩展
                reportDto.setTrip_weekday_count(multiply(weekdayDays, coefficient).floatValue());

                long mileage = Optional.ofNullable((Long)row.getAs("mileage")).orElse(0L);
                //里程扩展
                reportDto.setMileage_sum(multiply(mileage, coefficient).doubleValue());
                reportDto.setMileage_daily(divide(mileage, spanDays));
                reportDto.setMileage_monthly(divideDouble(mileage, spanMonths));

                long duration = Optional.ofNullable((Long)row.getAs("duration")).orElse(0L);
                //时长扩展
                reportDto.setDuration_sum( multiply(duration, coefficient).floatValue());
                reportDto.setDuration_daily(divide(duration, spanDays));
                reportDto.setDuration_weekly(divide(duration, spanDays) *7);
                reportDto.setDuration_monthly(divide(duration, spanMonths));

                reportDto.setAvg_speed_daily(divide(mileage, duration));
                //月平均速度计算公式？？
                reportDto.setAvg_speed_monthly(divide(mileage, duration));

                long fatigueDuration = Optional.ofNullable((Long)row.getAs("fatigue_duration")).orElse(0L);
                //疲劳驾驶时长扩展
                reportDto.setFatigue_duration(multiply(fatigueDuration, coefficient).floatValue());
                reportDto.setFatigue_duration_daily(divide(fatigueDuration, spanDays));
                reportDto.setFatigue_duration_monthly(divide(fatigueDuration, spanMonths));

                reportDto.setFatigue400_avg(divide(row.getAs("fatigue400_count"), row.getAs("trip400_count")));
                reportDto.setFatigue800_avg(divide(row.getAs("fatigue800_count"), row.getAs("trip800_count")));

                long overloadCount = Optional.ofNullable((Long)row.getAs("overload_count")).orElse(0L);
                //超载总次数扩展
                reportDto.setOverload_count(multiply(overloadCount, coefficient).floatValue());
                reportDto.setOverload_count_daily(divide(overloadCount, spanDays));
                reportDto.setOverload_count_monthly(divide(overloadCount, spanMonths));

                long sharpBrakeCount = Optional.ofNullable((Long)row.getAs("sharp_brake_count")).orElse(0L);
                //急刹次数扩展
                reportDto.setSharp_brake_count( multiply(sharpBrakeCount, coefficient).floatValue());
                reportDto.setSharp_brake_count_daily(divide(sharpBrakeCount, spanDays));
                reportDto.setSharp_brake_count_monthly(divide(sharpBrakeCount, spanMonths));

                long sharpCount = Optional.ofNullable((Long)row.getAs("sharp_accelerator_count")).orElse(0L);
                //急油门扩展
                reportDto.setSharp_accelerator_count(multiply(sharpCount, coefficient).floatValue());
                reportDto.setSharp_accelerator_count_daily(divide(sharpCount, spanDays));
                reportDto.setSharp_accelerator_count_monthly(divide(sharpCount, spanMonths));

                long ngCoastCount = Optional.ofNullable((Long)row.getAs("ng_coast_count")).orElse(0L);
                //空档滑行扩展
                reportDto.setNg_coast_count(multiply(ngCoastCount, coefficient).floatValue());
                reportDto.setNg_coast_count_daily(divide(ngCoastCount, spanDays));
                reportDto.setNg_coast_count_monthly(divide(ngCoastCount, spanMonths));

                long igCoastCount = Optional.ofNullable((Long)row.getAs("ig_coast_count")).orElse(0L);
                //在档滑行扩展
                reportDto.setIg_coast_count( multiply(igCoastCount, coefficient).floatValue());
                reportDto.setIg_coast_count_daily(divide(igCoastCount, spanDays));
                reportDto.setIg_coast_count_monthly(divide(igCoastCount, spanMonths));

                long noonMileage = Optional.ofNullable((Long)row.getAs("noon_mileage")).orElse(0L);
                long nightMileage = Optional.ofNullable((Long)row.getAs("night_mileage")).orElse(0L);
                long noonDuration = Optional.ofNullable((Long)row.getAs("noon_duration")).orElse(0L);
                long nightDuration = Optional.ofNullable((Long)row.getAs("night_duration")).orElse(0L);

                reportDto.setNoon_duration_daily( divide(noonDuration, spanDays) );
                reportDto.setNoon_duration_weekly( divide(noonDuration, spanDays) *7 );
                reportDto.setNoon_duration_monthly( divide(noonDuration, spanMonths) );
                reportDto.setNoon_mileage_daily( divide(noonMileage, spanDays) );
                reportDto.setNoon_mileage_monthly( divideDouble(noonMileage, spanMonths) );
                reportDto.setNight_duration_daily( divide(nightDuration, spanDays) );
                reportDto.setNight_duration_weekly( divide(nightDuration, spanDays) *7 );
                reportDto.setNight_duration_monthly( divide(nightDuration, spanMonths) );
                reportDto.setNight_mileage_daily( divide(nightMileage, spanDays) );
                reportDto.setNight_mileage_monthly( divideDouble(nightMileage, spanMonths) );

                WrappedArray.ofRef mileageDetail = row.getAs("mileage_detail");
                if(null != mileageDetail){
                    List<Long> dayList = new ArrayList<>();
                    List<Long> monthList = new ArrayList<>();

                    Object[] monthArr = mileageDetail.array();
                    for(int i=0; i<monthArr.length; i++){
                        Long[] dayArr = ((WrappedArray.ofRef<Long>)monthArr[i]).array();
                        long monthMil = 0;
                        for(Long dayMil : dayArr){
                            monthMil += dayMil;
                            dayList.add(dayMil);
                        }
                        monthList.add(monthMil);
                    }

                    reportDto.setMileage_cv_daily( seekCV(dayList));
                    reportDto.setMileage_cv_monthly( seekCV(monthList));
                }

                //新增字段需求
                dealNewColumn(row, reportDto, coefficient);

                list.add(reportDto);
            }
            return list.iterator();
        }, Encoders.bean(DrivingReport.class));

        //保存数据到表中
        String dbName = configMap.get("hive.insurance.db");
        String tableName = configMap.get("hive.insurance.report.table");
        String columns = configMap.get("hive.insurance.report.columns");
        List<String> partationKeys = Collections.singletonList("day");

        String startDate = configMap.get("args_1");//统计的起始时间
        String endDate = configMap.get("args_2");   //统计的结束时间（包含）
        List<Object> partationValues = Collections.singletonList(startDate + "_"+endDate);
        BigDataUtils.saveDataSetToHiveTable(spark, drivingReportDS, BigDataUtils.CoalesceType.repartation, 1, dbName, tableName, partationKeys, partationValues,  Lists.newArrayList(columns.split(",")));
    }

    /**
     *  新增字段需求
     * @param row
     * @param drivingInfo
     */
    private void dealNewColumn(Row row, DrivingReport reportDto, float coefficient) {
        reportDto.setIs0F37(Optional.ofNullable((Short)(row.getAs("is0F37"))).orElse((short)0));
        reportDto.setFuel_sum(multiply(Optional.ofNullable((Long)(row.getAs("fuel_sum"))).orElse(0L), coefficient).floatValue());
        reportDto.setFout_count(multiply(Optional.ofNullable((Long)(row.getAs("fout_count"))).orElse(0L), coefficient).floatValue());
        reportDto.setShift_gears_count(multiply(Optional.ofNullable((Long)(row.getAs("shift_gears_count"))).orElse(0L), coefficient).floatValue());
        reportDto.setSharp_turning_count(multiply(Optional.ofNullable((Long)(row.getAs("sharp_turning_count"))).orElse(0L), coefficient).floatValue());
        reportDto.setIdle_duration(multiply(Optional.ofNullable((Long)(row.getAs("idle_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setEngine_work_duration(multiply(Optional.ofNullable((Long)(row.getAs("engine_work_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIg_coast_mileage(multiply(Optional.ofNullable((Long)(row.getAs("ig_coast_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setIg_coast_duration(multiply(Optional.ofNullable((Long)(row.getAs("ig_coast_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setBrake_mileage(multiply(Optional.ofNullable((Long)(row.getAs("brake_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setBrake_duration(multiply(Optional.ofNullable((Long)(row.getAs("brake_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setCity_driving_mileage(multiply(Optional.ofNullable((Long)(row.getAs("city_driving_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setCity_driving_duration(multiply(Optional.ofNullable((Long)(row.getAs("city_driving_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRural_driving_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rural_driving_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRural_driving_duration(multiply(Optional.ofNullable((Long)(row.getAs("rural_driving_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setEco_driving_mileage(multiply(Optional.ofNullable((Long)(row.getAs("eco_driving_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setEco_driving_duration(multiply(Optional.ofNullable((Long)(row.getAs("eco_driving_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSharp_brake_mileage(multiply(Optional.ofNullable((Long)(row.getAs("sharp_brake_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSharp_brake_duration(multiply(Optional.ofNullable((Long)(row.getAs("sharp_brake_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSharp_up_speed_mileage(multiply(Optional.ofNullable((Long)(row.getAs("sharp_up_speed_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSharp_up_speed_duration(multiply(Optional.ofNullable((Long)(row.getAs("sharp_up_speed_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSharp_up_speed_count(multiply(Optional.ofNullable((Long)(row.getAs("sharp_up_speed_count"))).orElse(0L), coefficient).floatValue());
        reportDto.setSharp_accelerator_mileage(multiply(Optional.ofNullable((Long)(row.getAs("sharp_accelerator_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSharp_accelerator_duration(multiply(Optional.ofNullable((Long)(row.getAs("sharp_accelerator_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setVehicle_start_count(multiply(Optional.ofNullable((Long)(row.getAs("vehicle_start_count"))).orElse(0L), coefficient).floatValue());
        reportDto.setVehicle_cold_start_count(multiply(Optional.ofNullable((Long)(row.getAs("vehicle_cold_start_count"))).orElse(0L), coefficient).floatValue());
        reportDto.setAssist_brake_mileage(multiply(Optional.ofNullable((Long)(row.getAs("assist_brake_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setAssist_brake_duration(multiply(Optional.ofNullable((Long)(row.getAs("assist_brake_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range01_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range01_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range01_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range01_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range02_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range02_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range02_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range02_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range03_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range03_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range03_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range03_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range04_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range04_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range04_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range04_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range05_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range05_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range05_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range05_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range06_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range06_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range06_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range06_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range07_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range07_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range07_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range07_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range08_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range08_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range08_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range08_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range09_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range09_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range09_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range09_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range10_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range10_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range10_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range10_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range11_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range11_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range11_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range11_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setSpeed_range12_mileage(multiply(Optional.ofNullable((Long)(row.getAs("speed_range12_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setSpeed_range12_duration(multiply(Optional.ofNullable((Long)(row.getAs("speed_range12_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear01_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear01_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear01_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear01_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear02_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear02_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear02_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear02_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear03_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear03_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear03_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear03_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear04_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear04_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear04_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear04_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear05_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear05_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear05_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear05_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear06_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear06_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear06_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear06_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear07_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear07_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear07_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear07_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear08_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear08_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear08_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear08_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear09_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear09_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear09_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear09_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear10_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear10_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear10_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear10_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear11_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear11_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear11_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear11_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear12_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear12_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear12_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear12_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear13_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear13_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear13_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear13_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear14_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear14_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear14_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear14_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear15_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear15_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear15_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear15_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear16_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear16_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear16_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear16_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGear_other_mileage(multiply(Optional.ofNullable((Long)(row.getAs("gear_other_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setGear_other_duration(multiply(Optional.ofNullable((Long)(row.getAs("gear_other_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_range500_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range500_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_range500_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range500_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_range800_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range800_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_range800_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range800_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_range1100_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range1100_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_range1100_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range1100_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_range1400_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range1400_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_range1400_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range1400_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_range1700_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range1700_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_range1700_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range1700_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_range2000_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range2000_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_range2000_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range2000_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_range2300_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range2300_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_range2300_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range2300_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_range2600_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range2600_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_range2600_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_range2600_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setRpm_rangeGT2600_mileage(multiply(Optional.ofNullable((Long)(row.getAs("rpm_rangeGT2600_mileage"))).orElse(0L), coefficient).doubleValue());
        reportDto.setRpm_rangeGT2600_duration(multiply(Optional.ofNullable((Long)(row.getAs("rpm_rangeGT2600_duration"))).orElse(0L), coefficient).floatValue());
        long rpm_sum = Optional.ofNullable((Long)row.getAs("rpm_sum")).orElse(0L);
        long rpm_count= Optional.ofNullable((Long)row.getAs("rpm_count")).orElse(0L);
        reportDto.setRpm_avg(divide(rpm_sum, rpm_count));

        reportDto.setGas_open0_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open0_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open10_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open10_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open20_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open20_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open30_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open30_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open40_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open40_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open50_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open50_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open60_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open60_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open70_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open70_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open80_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open80_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open90_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open90_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open99_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open99_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setGas_open100_duration(multiply(Optional.ofNullable((Long)(row.getAs("gas_open100_duration"))).orElse(0L), coefficient).floatValue());
        long gas_open_sum = Optional.ofNullable((Long)row.getAs("gas_open_sum")).orElse(0L);
        long gas_open_count= Optional.ofNullable((Long)row.getAs("gas_open_count")).orElse(0L);
        reportDto.setGas_open_avg(divide(gas_open_sum, gas_open_count));

        reportDto.setTorque0_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque0_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque10_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque10_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque20_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque20_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque30_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque30_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque40_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque40_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque50_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque50_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque60_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque60_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque70_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque70_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque80_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque80_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque90_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque90_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque99_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque99_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setTorque100_duration(multiply(Optional.ofNullable((Long)(row.getAs("torque100_duration"))).orElse(0L), coefficient).floatValue());
        long torque_sum = Optional.ofNullable((Long)row.getAs("torque_sum")).orElse(0L);
        long torque_count= Optional.ofNullable((Long)row.getAs("torque_count")).orElse(0L);
        reportDto.setTorque_avg(divide(torque_sum, torque_count));

        reportDto.setIat50_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat50_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat70_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat70_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat80_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat80_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat85_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat85_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat90_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat90_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat95_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat95_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat100_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat100_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat105_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat105_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat110_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat110_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat115_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat115_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat120_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat120_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat125_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat125_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat130_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat130_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat135_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat135_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat140_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat140_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat145_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat145_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIat150_duration(multiply(Optional.ofNullable((Long)(row.getAs("iat150_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIatGT150_duration(multiply(Optional.ofNullable((Long)(row.getAs("iatGT150_duration"))).orElse(0L), coefficient).floatValue());
        long iat_sum = Optional.ofNullable((Long)row.getAs("iat_sum")).orElse(0L);
        long iat_count= Optional.ofNullable((Long)row.getAs("iat_count")).orElse(0L);
        reportDto.setIat_avg(divide(iat_sum, iat_count));

        reportDto.setIp50_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip50_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp60_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip60_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp70_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip70_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp80_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip80_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp90_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip90_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp100_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip100_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp110_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip110_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp120_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip120_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp130_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip130_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp140_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip140_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIp150_duration(multiply(Optional.ofNullable((Long)(row.getAs("ip150_duration"))).orElse(0L), coefficient).floatValue());
        reportDto.setIpGT150_duration(multiply(Optional.ofNullable((Long)(row.getAs("ipGT150_duration"))).orElse(0L), coefficient).floatValue());
        long ip_sum = Optional.ofNullable((Long)row.getAs("ip_sum")).orElse(0L);
        long ip_count= Optional.ofNullable((Long)row.getAs("ip_count")).orElse(0L);
        reportDto.setIp_avg(divide(ip_sum, ip_count));
    }

        /**
         * 相处，返回保留2位的Float
         * @param n
         * @param m
         * @return
         */
    private float divide(long n, long m){
        if( n == 0 || m == 0){
            return 0.00F;
        }
        return BigDecimal.valueOf(n).divide(BigDecimal.valueOf(m),2 , BigDecimal.ROUND_HALF_UP).floatValue();
    }

    private double divideDouble(long n, long m){
        if( n == 0 || m == 0){
            return 0.00d;
        }
        return BigDecimal.valueOf(n).divide(BigDecimal.valueOf(m),2 , BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    private float divide(double n, long m){
        if( n == 0 || m == 0){
            return 0.00F;
        }
        return BigDecimal.valueOf(n).divide(BigDecimal.valueOf(m),2 , BigDecimal.ROUND_HALF_UP).floatValue();
    }

    private float divide(double n, double m){
        if( n == 0 || m == 0){
            return 0.00F;
        }
        return BigDecimal.valueOf(n).divide(BigDecimal.valueOf(m),2 , BigDecimal.ROUND_HALF_UP).floatValue();
    }

    private BigDecimal multiply(long n, float m){
        if( n == 0 || m == 0){
            return BigDecimal.valueOf(0.00);
        }
        return BigDecimal.valueOf(n).multiply(BigDecimal.valueOf(m));
    }

    /**
     * 求CV，CV=标准差/平均数
     * @param list
     */
    private float seekCV(List<Long> list) {
        int length = list.size();
        //平均值
        double avg = list.stream().mapToInt(Long::intValue).average().orElse(0.0);
        if(avg==0.0){
            return 0.0f;
        }

        //方差
        double var=0;
        for(int i=0; i<length; i++){
            var += Math.pow( list.get(i), 2);
        }

        //计算va
        double va = length<=1 ? var : BigDecimal.valueOf(var).divide(BigDecimal.valueOf(length-1), 2 , BigDecimal.ROUND_HALF_UP).doubleValue();

        //标准差
        double sd = Math.sqrt(va);
        return BigDecimal.valueOf(sd).divide(BigDecimal.valueOf(avg),2 , BigDecimal.ROUND_HALF_UP).floatValue();
    }

}